package com.dbpms.pj.sys.service.impl;

import com.dbpms.pj.common.exception.ServiceException;
import com.dbpms.pj.common.pojo.PageObject;
import com.dbpms.pj.sys.dao.SysUserDao;
import com.dbpms.pj.sys.dao.SysUserRoleDao;
import com.dbpms.pj.sys.pojo.SysUser;
import com.dbpms.pj.sys.pojo.SysUserDept;
import com.dbpms.pj.sys.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @Author: Song Yu
 * @Date: 2020/10/20 19:10
 */

//Transactional注解描述的方法为事务切入点方法,这个方法在执行之前会开启事务,方法执行之后会提交或回滚事务
@Transactional(readOnly = false,
        rollbackFor =Throwable.class,
        timeout = 60,
        isolation = Isolation.READ_COMMITTED,
        propagation = Propagation.REQUIRED)
@Slf4j
@Service
public class SysUserServiceImpl implements SysUserService {
    @Autowired
    SysUserDao sysUserDao;

    @Autowired
    SysUserRoleDao sysUserRoleDao;

    @Override
    public PageObject<SysUserDept> findPageObjects(String username, Integer pageCurrent) {
        if(pageCurrent<=0||pageCurrent==null)
            throw new ServiceException("当前页码值不正确");
        int rowCount = sysUserDao.getRowCount(username);
        if(rowCount == 0)
            throw new ServiceException("没有找到对应记录");
        int pageSize = 5;
        int startIndex = (pageCurrent-1)*pageSize;
        List<SysUserDept> records = sysUserDao.findPageObjects(username,startIndex,pageSize);
        return new PageObject<>(pageCurrent,pageSize,rowCount,records);
    }

    @Override
    public int updateValidById(Integer id, Integer valid) {
        //1.合法性验证
        if(id==null||id<=0)
            throw new ServiceException("参数不合法,id="+id);
        if(valid==null||(valid!=1&&valid!=0))
            throw new ServiceException("参数不合法,valid="+valid);
        //2.执行禁用或启用操作(admin为后续登陆用户）
        int rows=sysUserDao.updateValidById(id, valid,"admin");
        //3.判定结果,并返回
        if(rows==0)
            throw new ServiceException("此记录可能已经不存在");
        return rows;
    }


    @Async //此方法在运行时会在一个独立的线程中
    @Transactional //默认为Propagation。REQUIRED
    //@Transactional(propagation=Propagation.REQUIRES_NEW)
    @Override
    public int saveObject(SysUser entity, Integer[] roleIds) {
        long start=System.currentTimeMillis();
        log.info("start:"+start);
        //1.参数校验
        if(entity==null)
            throw new IllegalArgumentException("保存对象不能为空");
        if(StringUtils.isEmpty(entity.getUsername()))
            throw new IllegalArgumentException("用户名不能为空");
        if(StringUtils.isEmpty(entity.getPassword()))
            throw new IllegalArgumentException("密码不能为空");
        if(roleIds==null || roleIds.length==0)
            throw new IllegalArgumentException("至少要为用户分配角色");
        //2.保存用户自身信息
        //2.1对密码进行加密
        String source=entity.getPassword();
        String salt= UUID.randomUUID().toString();
        SimpleHash sh=new SimpleHash(//Shiro框架
                "MD5",//algorithmName 算法
                source,//原密码
                salt, //盐值
                1);//hashIterations表示加密次数
        entity.setSalt(salt);
        entity.setPassword(sh.toHex());
        int rows=sysUserDao.insertObject(entity);
        //3.保存用户角色关系数据
        sysUserRoleDao.insertObjects(entity.getId(), roleIds);
        System.out.println("userId="+entity.getId());
        long end=System.currentTimeMillis();
        log.info("end:"+end);
        log.info("total time :"+(end-start));
        //4.返回结果
        return rows;
    }

    //方法上事务特性优先级要高于类上定义的事务特性.
    @Transactional(readOnly = true)//建议所有查询操作,事务的readOnly属性值改为true
    @Override
    public Map<String, Object> findObjectById(Integer id) {
        SysUserDept user = sysUserDao.findObjectById(id);
        Integer[] roleIds = sysUserRoleDao.findRoleIdsByUserId(id);
        Map<String,Object> map = new HashMap<>();
        map.put("user",user);
        map.put("roleIds",roleIds);
        return map;
    }

    @Override
    public int updateObject(SysUser entity, Integer[] roleIds) {
        if(entity==null)
            throw new ServiceException("保存对象不能为空");
        if(StringUtils.isEmpty(entity.getUsername()))
            throw new ServiceException("用户名不能为空");
        if(roleIds==null||roleIds.length==0)
            throw new ServiceException("必须为其指定角色");
        int rows=sysUserDao.updateObject(entity);
        sysUserRoleDao.deleteObjects(entity.getId());
        sysUserRoleDao.insertObjects(entity.getId(),roleIds);
        return rows;
    }
}
